﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using SeniorCapstoneProject.ServiceReference3;
using System.Threading;
using Client;
using System.Web;

namespace SeniorCapstoneProject
{
    class FileSendRecieve
    {

        public void StartTransfer(string fileInformation, int id, frmMain active, verifyUser hc, string groupName, int status, int parts)
        {
            if (File.Exists(fileInformation)) //Check to make sure file exists and has permissions to read
            {
                BackgroundThreads bgt = new BackgroundThreads(fileInformation, id, active, hc, groupName, status, parts); //Pass fileLocation and password to be used in thread
                Thread sjc = new Thread(new ThreadStart(bgt.TransferFile));
                string tryal = active.ReplaceString(Path.GetFileName(fileInformation)) + "_Transfer_Status";
                sjc.Name = tryal;
                sjc.IsBackground = true;
                active.threadStore.Add(sjc);
                sjc.Start(); //Start thread
            }
            else
            {
                //Post error for user
                active.Invoke(new UpdateMessageInvoker(active.UpdateMessageBoard), "***Error*** Either you don't have permissions to access this file, it is in use by another program, or the file no longer exists");
            }
        }

        public void StartDownload(string fileInformation, List<string> partsList, frmMain active, verifyUser hc, int status, string groupName)
        {
            BackgroundThreads bgt = new BackgroundThreads(fileInformation, partsList, active, hc, groupName, status); //Pass fileLocation and password to be used in thread
            Thread sjc = new Thread(new ThreadStart(bgt.DownloadFile));
            string tryal = active.ReplaceString(Path.GetFileName(fileInformation)) + "_Transfer_Status";
            sjc.Name = tryal;
            sjc.IsBackground = true;
            active.threadStore.Add(sjc);
            sjc.Start(); //Start thread
        }
    }

    public class BackgroundThreads
    {
        //frmMain form = frmMain.ActiveForm as frmMain; //Used to update status and messages
        private string fileInfos;
        private int id;
        private int parts;
        private frmMain form;
        private verifyUser hc;
        private string groupName;
        private int status;
        private List<string> partsList;

        private string FileInfo
        {
            get
            {
                return fileInfos;
            }
            set
            {
                fileInfos = value;
            }
        }

        private int ID
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }

        public BackgroundThreads(string location, List<string> partsList, frmMain active, verifyUser hc, string groupName, int status)
        {
            FileInfo = location;
            this.form = active;
            this.hc = hc;
            this.groupName = groupName;
            this.status = status;
            this.partsList = partsList;
        }

        public BackgroundThreads(string location, int id, frmMain active, verifyUser hc, string groupName, int status, int parts)
        {
            FileInfo = location;
            ID = id;
            this.form = active;
            this.hc = hc;
            this.groupName = groupName;
            this.status = status;
            this.parts = parts;
        }

        public void TransferFile()
        {
            form.threadTransfer[ID].Reset();
            try
            {
                if (ID > 0)
                {
                    form.threadTransfer[ID - 1].WaitOne(Timeout.Infinite);
                }

                // get some info about the input file
                FileInfo fileInfo = new FileInfo(FileInfo);

                // open input stream
                using (FileStream stream = new FileStream(FileInfo, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    using (StreamWithProgress uploadStreamWithProgress = new StreamWithProgress(stream, form, status))
                    {
                        frmMain frmM = new frmMain();
                        uploadStreamWithProgress.ProgressChanged += uploadStreamWithProgress.pgBar_Changed;
                        
                        // start service client
                        RemoteFileInfo client = new RemoteFileInfo();
                        TransferFilesClient clientUpload = new TransferFilesClient();

                        client.FileName = Path.GetFileName(FileInfo);
                        client.FileSize = fileInfo.Length;
                        client.FileByteStream = stream;
                        client.UserName = hc.Username;
                        client.Password = hc.Password;
                        client.Group = groupName;
                        client.FileStart = 0;
                        client.NumParts = parts;
                        
                        if (!FileInfo.Contains("password"))
                        {
                            FileStatus fs = new FileStatus();
                            fs.FileName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(client.FileName));
                            fs.Location = FileInfo;
                            fs.FilePart = Path.GetFileNameWithoutExtension(client.FileName);
                            fs.Group = client.Group;
                            fs.Tree = "trvLocal";

                            int found = 0;
                            foreach (FileStatus fsTest in form.fileContinuation.ToList())
                            {
                                if (fsTest.FileName == fs.FileName)
                                {
                                    fsTest.Location = fs.Location;
                                    fsTest.FilePart = fs.FilePart;
                                    found = 1;
                                    break;
                                }
                            }

                            if (found == 0)
                            {
                                form.fileContinuation.Add(fs);
                            }
                        }
                        form.threadActivity[status].WaitOne(Timeout.Infinite);

                        clientUpload.UploadFile( client.FileName, client.FileSize, client.FileStart, client.Group, client.NumParts, client.Password, client.UserName, uploadStreamWithProgress);
                    }
                }
                form.threadTransfer[ID].Set();
                form.Invoke(new pgBar_Update(form.pgBar_update), -1, -1, fileInfo.FullName);
            }
            catch (Exception ex)
            {

            }
        }

        public void DownloadFile()
        {
            try
            {
                TransferFilesClient tfc = new TransferFilesClient();
                RemoteFileInfo rfi = new RemoteFileInfo();
                DownloadRequest requestData = new DownloadRequest();
                FileStream targetStream = null;
                String filePath = "";

                foreach(string tempList in partsList.ToList())
                {
                    requestData.FileName = FileInfo;
                    requestData.FilePart = tempList;
                    requestData.Password = hc.Password;
                    requestData.UserName = hc.Username;

                    if (!requestData.FilePart.Contains("password.7z"))
                    {
                        FileStatus fs = new FileStatus();
                        fs.FileName = Path.GetFileName(requestData.FileName);
                        fs.Location = FileInfo;
                        fs.FilePart = Path.GetFileNameWithoutExtension(requestData.FilePart);
                        fs.Group = groupName;
                        fs.Tree = "trvRemote";

                        int found = 0;
                        foreach (FileStatus fsTest in form.fileContinuation.ToList())
                        {
                            if (fsTest.FileName == fs.FileName)
                            {
                                fsTest.Location = fs.Location;
                                fsTest.FilePart = fs.FilePart;
                                found = 1;
                                break;
                            }
                        }

                        if (found == 0)
                        {
                            form.fileContinuation.Add(fs);
                        }
                    }

                    form.threadActivity[status].WaitOne(Timeout.Infinite);

                    string activeDir = Properties.Settings.Default.Temp + "\\hct\\";
                    string newPath = activeDir + "\\" + hc.Username + "\\Downloads\\" + Path.GetFileNameWithoutExtension(requestData.FileName);
                    Directory.CreateDirectory(newPath);
                    filePath = Path.Combine(newPath, requestData.FilePart);

                    rfi.FileSize = tfc.DownloadFile(ref requestData.FileName, requestData.FilePart, ref requestData.Password, ref requestData.UserName, out rfi.FileStart, out rfi.Group, out rfi.NumParts, out rfi.FileByteStream);

                    Stream sourceStream = rfi.FileByteStream;
                    using (targetStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        const int bufferLen = 65000;
                        byte[] buffer = new byte[bufferLen];
                        int bytesRead = 0;

                        int count = 0;

                        bytesRead = rfi.FileByteStream.Read(buffer, 0, buffer.Length);
                        count += bytesRead;

                        while (bytesRead > 0)
                        {
                            targetStream.Write(buffer, rfi.FileStart, bytesRead);
                            form.Invoke(new pgBar_Update(form.pgBar_update), count, rfi.FileSize, requestData.FilePart);
                            bytesRead = rfi.FileByteStream.Read(buffer, 0, buffer.Length);
                            count += bytesRead;
                        }
                        targetStream.Close();
                        sourceStream.Close();

                        SplitJoinCompress sjc = new SplitJoinCompress();

                        if (!requestData.FilePart.Contains("password.7z"))
                        {
                            sjc.DecompressFiles(filePath, newPath + "\\" + Path.GetFileName(requestData.FileName) + ".password.7z", hc, form);
                        }

                        if (tempList != partsList[partsList.Count() - 1])
                        {
                            form.Invoke(new pgBar_Update(form.pgBar_update), -1, -1, requestData.FileName);
                        }
                    }
                }
                FileSpliterJoiner fsj = new FileSpliterJoiner();
                fsj.BeginJoinFiles(Path.GetDirectoryName(filePath) + "\\" + Path.GetFileNameWithoutExtension(partsList[partsList.Count() - 1]), form);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
        }
    }
}
